﻿//
//                       _oo0oo_
//                      o8888888o
//                      88" . "88
//                      (| -_- |)
//                      0\  =  /0
//                    ___/`---'\___
//                  .' \\|     |// '.
//                 / \\|||  :  |||// \
//                / _||||| -:- |||||- \
//               |   | \\\  -  /// |   |
//               | \_|  ''\---/''  |_/ |
//               \  .-\__  '-'  ___/-. /
//             ___'. .'  /--.--\  `. .'___
//          ."" '<  `.___\_<|>_/___.' >' "".
//         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//         \  \ `_.   \_ __\ /__ _/   .-` /  /
//     =====`-.____`.___ \_____/___.-`___.-'=====
//                       `=---='
//
//
//     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//               佛祖保佑         永无BUG
//
//     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#region << 版 本 注 释 >>

/*----------------------------------------------------------------
* 类 名 称 ：Actor
* 类 描 述 ：
* 作    者 ：henrychang
* 创建时间 ：2019/1/26 16:20:55
*******************************************************************
* Copyright @ henrychang 2018. All rights reserved.
*******************************************************************
//----------------------------------------------------------------*/

#endregion << 版 本 注 释 >>

using TouchFish.Component;
using UnityEngine;

namespace TouchFish.Actor
{
    public abstract class Actor : MonoBehaviour, IActor
    {
        private void Awake()
        {
            Init();
        }

        private IComponentContainer _componentContainer;

        protected virtual IComponentContainer ComponentContainer
        {
            get
            {
                if (_componentContainer == null)
                {
                    _componentContainer = new ComponentContainer(ComponentView.ComponentContainer);
                    Add(_componentContainer);
                }
                return _componentContainer;
            }
        }

        public string Name { get; set; }
        private int _roleId;

        public int RoleID
        {
            get
            {
                return _roleId;
            }
        }

        public Transform SelfTransform { get { return transform; } }

        public GameObject SelfGameObject { get { return gameObject; } }

        private event UpdateDele _onUpdate;

        private event UpdateDele _onFixedUpdate;

        private event UpdateDele _onLateUpdate;

        public event UpdateDele OnUpdate
        {
            add
            {
                _onUpdate += value;
            }
            remove
            {
                _onUpdate -= value;
            }
        }

        public event UpdateDele OnFixedUpdate
        {
            add
            {
                _onFixedUpdate += value;
            }
            remove
            {
                _onFixedUpdate -= value;
            }
        }

        public event UpdateDele OnLateUpdate
        {
            add
            {
                _onLateUpdate += value;
            }
            remove
            {
                _onLateUpdate -= value;
            }
        }

        IActor IComponent.Actor
        {
            get
            {
                return this;
            }
            set { }
        }

        public virtual void Init()
        {
            AddComponents();
        }

        public abstract void AddComponents();

        #region Update

        private void Update()
        {
            UpdateExecute();
        }

        private void FixedUpdate()
        {
            FixedExecute();
        }

        private void LateUpdate()
        {
            LateExecute();
        }

        public virtual void UpdateExecute()
        {
            if (_onUpdate != null)
            {
                _onUpdate();
            }
        }

        public virtual void FixedExecute()
        {
            if (_onFixedUpdate != null)
            {
                _onFixedUpdate();
            }
        }

        public virtual void LateExecute()
        {
            if (_onLateUpdate != null)
            {
                _onLateUpdate();
            }
        }

        #endregion Update

        public void Dispose()
        {
            ComponentContainer.Dispose();
        }

        #region Component

        public void Add(IComponent component)
        {
            component.Actor = this;
            ComponentContainer.Add(component);
        }

        public void AddUpdateEvent(string componentName)
        {
            RemoveUpdateEvent(componentName);
            OnUpdate += Get(componentName).UpdateExecute;
        }

        public void AddFixedUpdateEvent(string componentName)
        {
            RemoveFixedUpdateEvent(componentName);
            OnFixedUpdate += Get(componentName).FixedExecute;
        }

        public void AddLateUpdateEvent(string componentName)
        {
            RemoveLateEvent(componentName);
            OnLateUpdate += Get(componentName).LateExecute;
        }

        public void RemoveUpdateEvent(string componentName)
        {
            OnUpdate -= Get(componentName).UpdateExecute;
        }

        public void RemoveFixedUpdateEvent(string componentName)
        {
            OnFixedUpdate -= Get(componentName).FixedExecute;
        }

        public void RemoveLateEvent(string componentName)
        {
            OnLateUpdate -= Get(componentName).LateExecute;
        }

        public IComponent Get(string componentName)
        {
            return ComponentContainer.Get(componentName);
        }

        public bool IsComponentExist(string componentName)
        {
            return ComponentContainer.IsComponentExist(componentName);
        }

        public void Remove(string componentName)
        {
            ComponentContainer.Remove(componentName);
        }

        public void Remove(IComponent component)
        {
            ComponentContainer.Remove(component);
        }

        T IComponentContainer.Get<T>(string componentName)
        {
            return ComponentContainer.Get<T>(componentName);
        }

        public virtual void InitAdd()
        {
        }

        #endregion Component
    }
}